package health_system.health_system.repository;


import health_system.health_system.entity.Moment;
import health_system.health_system.entity.MomentShare;
import health_system.health_system.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface MomentShareRepository extends JpaRepository<MomentShare, Long> {
    
    // Find share by user and moment
    Optional<MomentShare> findByUserAndOriginalMoment(User user, Moment originalMoment);
    
    // Find all shares of a moment
    List<MomentShare> findByOriginalMomentOrderByCreatedAtDesc(Moment originalMoment);
    
    // Find with pagination
    Page<MomentShare> findByOriginalMomentOrderByCreatedAtDesc(Moment originalMoment, Pageable pageable);
    
    // Find all moments shared by a user
    List<MomentShare> findByUserOrderByCreatedAtDesc(User user);
    
    // Find with pagination
    Page<MomentShare> findByUserOrderByCreatedAtDesc(User user, Pageable pageable);
    
    // Check if user has shared a moment
    boolean existsByUserAndOriginalMoment(User user, Moment originalMoment);
    
    // Delete share
    void deleteByUserAndOriginalMoment(User user, Moment originalMoment);
    
    // Count shares for a moment
    Long countByOriginalMoment(Moment originalMoment);
    
    // Count shares by user
    Long countByUser(User user);
    
    // Find users who shared a moment
    @Query("SELECT ms.user FROM MomentShare ms WHERE ms.originalMoment = :moment ORDER BY ms.createdAt DESC")
    List<User> findUsersWhoSharedMoment(@Param("moment") Moment moment);
    
    // Find with pagination
    @Query("SELECT ms.user FROM MomentShare ms WHERE ms.originalMoment = :moment ORDER BY ms.createdAt DESC")
    Page<User> findUsersWhoSharedMoment(@Param("moment") Moment moment, Pageable pageable);
    
    // Find moments with most shares in user's visible moments
    @Query("SELECT m, COUNT(ms) FROM Moment m LEFT JOIN m.shares ms WHERE " +
           // Same visibility filters as in MomentRepository
           "(" +
           "(m.visibility = 'PUBLIC') OR " +
           "(m.user = :viewer) OR " +
           "(m.visibility = 'FRIENDS' AND " +
           "EXISTS (SELECT f FROM Friendship f WHERE " +
           "((f.requester = m.user AND f.addressee = :viewer) OR " +
           "(f.requester = :viewer AND f.addressee = m.user)) AND f.status = 'ACCEPTED')) OR " +
           "(m.visibility = 'CUSTOM' AND :viewer MEMBER OF m.visibleToUsers)" +
           ") " +
           "GROUP BY m ORDER BY COUNT(ms) DESC")
    List<Object[]> findMomentsWithMostSharesVisibleToUser(@Param("viewer") User viewer, Pageable pageable);
    
    // Find most recently shared moments by a user's friends
    @Query("SELECT ms.originalMoment FROM MomentShare ms WHERE ms.user IN " +
           "(SELECT CASE WHEN f.requester = :user THEN f.addressee ELSE f.requester END " +
           "FROM Friendship f WHERE (f.requester = :user OR f.addressee = :user) AND f.status = 'ACCEPTED') " +
           "AND ms.originalMoment.visibility IN ('PUBLIC', 'FRIENDS') " +
           "ORDER BY ms.createdAt DESC")
    List<Moment> findRecentlySharedMomentsByFriends(@Param("user") User user, Pageable pageable);
    
    // Find original moments of shares with a specific comment
    @Query("SELECT ms.originalMoment FROM MomentShare ms WHERE ms.additionalComment LIKE %:searchTerm% " +
           "AND (" +
           "(ms.originalMoment.visibility = 'PUBLIC') OR " +
           "(ms.originalMoment.user = :viewer) OR " +
           "(ms.originalMoment.visibility = 'FRIENDS' AND " +
           "EXISTS (SELECT f FROM Friendship f WHERE " +
           "((f.requester = ms.originalMoment.user AND f.addressee = :viewer) OR " +
           "(f.requester = :viewer AND f.addressee = ms.originalMoment.user)) AND f.status = 'ACCEPTED')) OR " +
           "(ms.originalMoment.visibility = 'CUSTOM' AND :viewer MEMBER OF ms.originalMoment.visibleToUsers)" +
           ") " +
           "ORDER BY ms.createdAt DESC")
    List<Moment> findOriginalMomentsByShareComment(@Param("searchTerm") String searchTerm, @Param("viewer") User viewer);
} 